package com.cy.game

import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import androidx.core.view.forEachIndexed
import org.json.JSONArray
import java.lang.RuntimeException

// 左下脚为 (0,0)
class Board(val gameFragment: CyGameFragment) {

    companion object {

        const val ContentRow = 9
        const val ContentColumn = 9

        const val SelRegionRow = 3
        const val SelRegionColumn = 8

        // 每个格子边长
        const val SideW = 100f
        const val SideH = 110f
        const val LeftOffset = 50f
        const val RightOffset = 50f
        const val GapW = (1080f - 9 * SideW - LeftOffset - RightOffset) / 8f
        const val GapH = 0f

        // 下面的选择区域
        const val SelRow = 3
        const val SelColumn = 8
//        const val SelGap = (1080f - 8 * SideW - LeftOffset - RightOffset) / 7f
    }

    // 分为两部分
    // 1. content
    // 2. selRegion
    val lstContent = ArrayList<ArrayList<Item>>(Board.ContentRow)
    val lstSelRegion = ArrayList<ArrayList<Item>>(Board.SelRegionRow)

    // 内容只要和这个表对上了,就过关了
    val winTable = HashMap<Int, String>()
    lateinit var curItem: Item
    lateinit var proverbs: ArrayList<Proverb>

    fun initContents() {
        for (i in 0 until ContentRow) {
            val arr = ArrayList<Item>(ContentColumn)
            for (j in 0 until ContentColumn) {
                val item = Item(gameFragment, i, j)
                arr.add(item)
            }
            lstContent.add(arr)
        }

        for (i in 0 until SelRow) {
            val arr = ArrayList<Item>(SelRegionColumn)
            for (j in 0 until SelRegionColumn) {
                val item = Item(gameFragment, i, j)
                arr.add(item)
            }
            lstSelRegion.add(arr)
        }
    }

    fun getContentItem(x: Int, y: Int): Item = lstContent[x][y]
    fun getSelRegionItem(x: Int, y: Int): Item = lstSelRegion[x][y]

    private fun initItems(proverbs: List<Proverb>) {
        //  可以选择的汉字
        for (proverb in proverbs) {
            // 根据这个 初始化 winTable
            val item = getContentItem(proverb.xIdx, proverb.yIdx)
            item.enable = true

            // 1表示填充
            val value = proverb.content[0].toString()
            if (proverb.initStateArr[0] == 1) {
                item.value = value
            }

            // 同时初始化 winTable
            winTable[proverb.xIdx * ContentColumn + proverb.yIdx] = value

            if (proverb.orientation == Proverb.Orientation.Hori) {
                // 左到右
                for (i in 1..3) {
                    val tmpItem = getContentItem(proverb.xIdx, proverb.yIdx + i)
                    tmpItem.enable = true
                    val tmpValue = proverb.content[i].toString()
                    if (proverb.initStateArr[i] == 1) {
                        tmpItem.value = tmpValue
                    }
                    winTable[proverb.xIdx * ContentColumn + proverb.yIdx + i] = tmpValue
                }
            } else {
                // 上到下
                for (i in 1..3) {
                    val tmpItem = getContentItem(proverb.xIdx - i, proverb.yIdx)
                    tmpItem.enable = true
                    val tmpValue = proverb.content[i].toString()
                    if (proverb.initStateArr[i] == 1) {
                        tmpItem.value = tmpValue
                    }
                    winTable[(proverb.xIdx - i) * ContentColumn + proverb.yIdx] = tmpValue
                }
            }
        }

        val selWords = ArrayList<String>()
        for ((k,v) in winTable){
            val xIdx = k / ContentColumn
            val yIdx = k % ContentColumn
            val item = getContentItem(xIdx,yIdx)
            if (item.value == ""){
                selWords.add(v)
            }
        }

        // 下面选取的单词
        var comboxIdx = 0
        selWords.forEach {
            val xIdx = comboxIdx / SelColumn
            val yIdx = comboxIdx % SelColumn
            val item = getSelRegionItem(xIdx, yIdx)
            item.enable = true
            item.value = it
            comboxIdx++
        }
    }

    fun initLevel(jsonArray: JSONArray) {

        // 初始化
        initContents()

        proverbs = genProverbs(jsonArray)

        initItems(proverbs)

        // 绑定UI
        initItemsUI()

        // 初始化当前item
        curItem = initCurItem()
        gameFragment.setCurItem(curItem)

        // 绑定事件
        lstContent.forEach { arr ->
            arr.forEach { item ->
                // 只有空格子才添加时间,默认的格子不添加事件
                if (item.enable &&
                        item.state != ItemState.DefaultContentBg) {
                    item.registClickEvent()
                }
            }
        }

        lstSelRegion.forEach { arr ->
            arr.forEach { item ->
                if (item.enable && item.value != "") {
                    item.registSelRegionClickEvent()
                }
            }
        }
    }

    private fun initCurItem(): Item {

        // 优先找到词语第一个为空的位置
        val p = proverbs.find {p->
            val item0 = p.getItem0(this)
            return@find item0.value == ""
        }
        if (p != null){
            return p.getItem0(this)
        }

        for ((k, _) in winTable) {
            val xIdx = k / ContentColumn
            val yIdx = k % ContentColumn
            val item = getContentItem(xIdx, yIdx)
            if (item.value == "") {
                return item
            }
        }
        throw RuntimeException("init curItem error!")
    }

    private fun initItemsUI() {
        gameFragment.lstViews.forEachIndexed { rowIdx, arr ->
            arr.forEachIndexed { colIdx, child ->
                val item = lstContent[rowIdx][colIdx]
                item.frameLayout = child
                item.textView = child.getChildAt(0) as TextView
                item.textView!!.text = item.value
                if (winTable.containsKey(colIdx + rowIdx * ContentColumn)) {
                    if (item.value != "") {
                        item.state = ItemState.DefaultContentBg
                    } else {
                        item.state = ItemState.WaitFillBg
                    }
                } else {
                    item.frameLayout!!.visibility = View.INVISIBLE
                }
            }
        }


        gameFragment.lstSelRegionLinearLayout.forEachIndexed { rowIdx, layout ->
            layout.forEachIndexed { colIdx, child ->
                val item = lstSelRegion[rowIdx][colIdx]
                item.frameLayout = child as FrameLayout
                item.textView = item.frameLayout!!.getChildAt(0) as TextView
                item.textView!!.text = item.value
                if (item.value != "") {
                    item.state = ItemState.DefaultSelRegionBg
                } else {
                    item.frameLayout!!.visibility = View.INVISIBLE
                }
            }
        }
    }

    // 将关卡解析成 Proverbs
    private fun genProverbs(jsonArr: JSONArray): ArrayList<Proverb> {
        val lstProverb = ArrayList<Proverb>()
        for (i in 0 until jsonArr.length()) {
            val obj = jsonArr.getJSONObject(i)
            val idxPos = obj.getInt("p")

            val xIdx: Int
            val yIdx: Int
            if (idxPos < 10) {
                xIdx = idxPos
                yIdx = 0
            } else {
                xIdx = idxPos % 10
                yIdx = idxPos / 10
            }

            // 方向
            val oValue = obj.getInt("o")
            val ori = if (oValue == 0) Proverb.Orientation.Vert else Proverb.Orientation.Hori

            //
            val content = obj.getString("w")
            val s = obj.getInt("s")

            // 显示状态
            val initStateArr = numToStateArr(s)

            val proverb = Proverb(xIdx, yIdx, content, ori, initStateArr)
            lstProverb.add(proverb)
        }
        return lstProverb
    }

    private fun numToStateArr(num: Int): IntArray {
        var str = num.toString(2)
        while (str.length < 4) {
            str = "0$str"
        }
        return intArrayOf(str[0].toString().toInt(), str[1].toString().toInt(), str[2].toString().toInt(), str[3].toString().toInt())
    }

    // 判断是否过关
    fun checkWin(): Boolean {
        // 有一个格子对不上就没过关
        for ((k, v) in winTable) {
            val xIdx = k / ContentColumn
            val yIdx = k % ContentColumn
            if (getContentItem(xIdx, yIdx).value != v) {
                return false
            }
        }
        return true
    }

    //
    fun isFullFill(): Boolean {
        for ((k, _) in winTable) {
            val xIdx = k / ContentColumn
            val yIdx = k % ContentColumn
            if (getContentItem(xIdx, yIdx).value == "") {
                return false
            }
        }
        return true
    }

    fun findFirstEmptySelItem():Item{
        lstSelRegion.forEach { arr->
            arr.forEach { item->
                if (item.value == ""){
                    return item
                }
            }
        }
        throw RuntimeException("findFirstSelItem error!")
    }
    fun findSelItemByValue(value:String):Item?{
        lstSelRegion.forEach { arr->
            arr.forEach { item->
                if (item.enable && item.value == value){
                    return item
                }
            }
        }
        return null
    }

    fun findErrorItem(value:String):Item{
         for ((k,v) in winTable){
             val xIdx = k / ContentColumn
             val yIdx = k % ContentColumn
             val item = getContentItem(xIdx, yIdx)
             if (item.value == value && v != value){
                 return  item
             }
         }
        throw RuntimeException("findErrorItem error!")
    }

    fun selRegionContainValue(v:String):Boolean{
        lstSelRegion.forEach { arr->
            arr.forEach { item ->
                if (item.value == v){
                    return true
                }
            }
        }
        return false
    }


    fun calContentX(yIdx:Int):Float{
        return LeftOffset + (SideW + GapW) * yIdx
    }
    fun calContentY(xIdx:Int):Float{
        val height = SideH * ContentRow + GapH * (ContentRow - 1)
        return height - (SideH + GapH) * xIdx - SideH
    }

    fun findRelatedProverbs(item:Item):List<Proverb>{
        val x = item.xIdx
        val y = item.yIdx
        return proverbs.filter { p ->
            return@filter p.contains(x, y)
        }
    }

    fun findFirstErrorItem():Item{
        for ((k,v) in winTable){
            val xIdx = k / ContentColumn
            val yIdx = k % ContentColumn
            val item = getContentItem(xIdx, yIdx)
            if (item.value != "" && item.value != v) {
                return item
            }
        }
        throw RuntimeException("findFirstErrorItem error!")
    }

    fun findNextItem():Item{
        proverbs.forEach { p->
            if (!p.isFill(this)){
                val item0 = p.getItem0(this)
                if (item0.value == ""){
                    return item0
                }

                val item1 = p.getItem1(this)
                if (item1.value == ""){
                    return  item1
                }

                val item2 = p.getItem2(this)
                if (item2.value == ""){
                    return  item2
                }

                val item3 = p.getItem3(this)
                if (item3.value == ""){
                    return item3
                }
            }
        }
        throw RuntimeException("全部都满了....")
    }
}